package com.oanda.blackberry.ui;

import java.util.Vector;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.KeyListener;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ObjectChoiceField;
import net.rim.device.api.ui.container.FlowFieldManager;
import net.rim.device.api.ui.container.PopupScreen;
import net.rim.device.api.ui.decor.BackgroundFactory;
import net.rim.device.api.ui.decor.BorderFactory;

import com.oanda.blackberry.util.DefaultController;

public class CustomObjectChoiceField extends ObjectChoiceField {
    int fontColor;
    int width;
    int height;
    int titleColor = -1;
    String title;
    Bitmap bg = Bitmap.getBitmapResource("custom-object-choiceField-196x28.png");
    Object[] choices;
    boolean isFocused = false;
    Font textFont;
    int ms = 336;
    int c = 0;
    int d = 100;
    int leftPos = 110;
    int higlightedIndex = getSelectedIndex();

    boolean isShown = false;

    public CustomObjectChoiceField(int color) {
        this.fontColor = color;
    }

    public CustomObjectChoiceField(int color, String label, Object[] choices, int width, int height) {
        super(label, choices);
        this.fontColor = color;
        this.width = width;
        this.height = height;
        this.choices = choices;
    }

    public CustomObjectChoiceField(int titleColor, int color, String label, Object[] choices,
            int width, int height) {
        super("", choices);

        this.title = label;
        this.fontColor = color;
        this.titleColor = titleColor;
        this.width = width;
        this.height = height;
        this.choices = choices;

        setMargin(0, 0, 0, 5);
    }

    public void paint(Graphics g) {
        if (this.titleColor == -1) {
            this.titleColor = this.fontColor;
        }

        g.drawBitmap(200, 0, 196, 28, this.bg, 0, 0);

        g.setColor(this.titleColor);
        Font f = getFont().derive(0, 20);
        g.setFont(f);

        g.drawText(this.title, 0, (this.height - f.getHeight()) / 2);

        g.setColor(this.fontColor);

        int index = getSelectedIndex();

        int BG_COLOR = 4473924;
        int FG_COLOR = 14671839;

        if (this.isFocused) {
            g.setColor(BG_COLOR);
            g.fillRoundRect(205, 3, f.getAdvance((String) getChoice(index)) + 10,
                    f.getHeight() + 2, 5, 5);
            g.setColor(FG_COLOR);
            g.drawText((String) getChoice(index), 210, 5);
        } else {
            g.setColor(BG_COLOR);
            g.drawText((String) getChoice(index), 210, 5);
        }

        paintPopUp(g);
    }

    private void sleep(int time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException ex) {
        }
    }

    protected boolean navigationMovement(int dx, int dy, int status, int time) {
        if (dx > 0) {
            if (this.isShown) {
                if (this.higlightedIndex <= this.choices.length - 1)
                    this.higlightedIndex += 1;
                else {
                    this.higlightedIndex = 0;
                }
            }

        } else if (this.isShown) {
            if (this.higlightedIndex - 1 >= 0)
                this.higlightedIndex -= 1;
            else {
                this.higlightedIndex = (this.choices.length - 1);
            }

        }

        invalidate();

        if ((this.isShown) && (dy > 0)) {
            this.isShown = (!this.isShown);
            invalidate();
        }

        return super.navigationMovement(dx, dy, status, time);
    }

    void paintPopUp(Graphics g) {
        if (this.isShown) {
            g.setDrawingStyle(1, true);
            g.setColor(13882323);
            g.setGlobalAlpha(230);

            if (this.c <= this.ms) {
                g.fillRoundRect(this.leftPos + 1, 6, this.c, 24, 5, 5);
                sleep(35);
                invalidate();
                this.c += 100;
                this.d /= 2;
                return;
            }
            g.fillRoundRect(this.leftPos, 5, 336, 24, 5, 5);
            g.setColor(4473924);
            g.fillRoundRect(this.leftPos + 1, 6, 334, 22, 5, 5);

            g.setColor(16119285);
            g.setFont(DefaultController.getComponentFont(16));
            int c = 3;

            if ((this.higlightedIndex < 0) || (this.higlightedIndex >= this.choices.length)) {
                this.higlightedIndex = 0;
            }
            for (int i = 0; i < this.choices.length; i++) {
                if (this.higlightedIndex == i) {
                    g.setColor(7895160);
                    g.fillRoundRect(this.leftPos + 1 + c, 9,
                            g.getFont().getAdvance(this.choices[i].toString()) + 4, g.getFont()
                                    .getHeight() + 2, 3, 3);

                    g.setColor(13684944);
                    g.fillRoundRect(this.leftPos + c, 8,
                            g.getFont().getAdvance(this.choices[i].toString()) + 4, g.getFont()
                                    .getHeight() + 2, 3, 3);

                    g.setColor(6710886);
                } else {
                    g.setColor(16119285);
                }

                g.drawText(this.choices[i].toString() + "  ", this.leftPos + 2 + c, 8);
                c += g.getFont().getAdvance(this.choices[i].toString() + "  ");
            }
        } else {
            this.c = 0;
            this.higlightedIndex = getSelectedIndex();
        }
    }

    private void fieldChanged(String newChoice) {
        for (int i = 0; i < getSize(); i++) {
            if ((newChoice == null) || (!newChoice.equals(getChoice(i))))
                continue;
            setSelectedIndex(i);
            this.higlightedIndex = i;
            invalidate();
            break;
        }
    }

    private void requestChange() {
        invalidate();
    }

    public boolean trackwheelClick(int status, int time) {
        if (this.isShown) {
            setSelectedIndex(this.higlightedIndex);
        }

        this.isShown = (!this.isShown);

        if (this.isShown)
            requestChange();
        else {
            invalidate();
        }
        return true;
    }

    private void selectNextValue() {
        int i = getSelectedIndex();

        if (i == -1)
            return;

        if (i + 1 == this.choices.length) {
            setSelectedIndex(0);
            this.higlightedIndex = 0;
        } else {
            setSelectedIndex(i + 1);
            this.higlightedIndex = (i + 1);
        }

        invalidate();
    }

    private void selectPreviousValue() {
        int i = getSelectedIndex();

        if (i == -1)
            return;

        if (i - 1 == -1) {
            setSelectedIndex(this.choices.length - 1);
            this.higlightedIndex = (this.choices.length - 1);
        } else {
            setSelectedIndex(i - 1);
            this.higlightedIndex = (i - 1);
        }
        invalidate();
    }

    protected boolean keyChar(char key, int status, int time) {
        if ((key == '\n') || (key == ' ')) {
            if (this.isShown) {
                setSelectedIndex(this.higlightedIndex);
                this.isShown = false;
                invalidate();
            } else {
                selectNextValue();
            }
            return true;
        }
        if ((key == '\033') && (this.isShown)) {
            this.isShown = (!this.isShown);
            invalidate();
            return true;
        }
        return super.keyChar(key, status, time);
    }

    protected void layout(int maxWidth, int maxHeight) {
        setExtent(this.width, this.height);
    }

    public void setWidth(int width) {
        this.width = width;
        setExtent(width, this.height);
        invalidate();
    }

    public void setHeight(int height) {
        this.height = height;
        setExtent(this.width, height);
        invalidate();
    }

    public void setTitleColor(int titleColor) {
        this.titleColor = titleColor;
    }

    public void setFontColor(int fontColor) {
        this.fontColor = fontColor;
    }

    public boolean isFocusable() {
        return true;
    }

    protected void drawFocus(Graphics graphics, boolean on) {
    }

    protected void onFocus(int direction) {
        this.isFocused = true;
        super.onFocus(direction);
        invalidate();
    }

    protected void onUnfocus() {
        if (this.isShown) {
            this.isShown = false;
        }
        this.isFocused = false;
        super.onUnfocus();
        invalidate();
    }

    protected void makeContextMenu(ContextMenu contextMenu) {
    }

    public void setTextFont(Font textFont) {
        this.textFont = textFont;
    }

    private class CustomPopupScreen extends PopupScreen implements KeyListener, FieldChangeListener {
        Vector results;
        LabelField label;
        SelectionListener listener;

        public CustomPopupScreen(Object[] choices, int selected, SelectionListener listener) {
            super(new FlowFieldManager());

            this.listener = listener;
            for (int i = 0; i < choices.length; i++) {
                Object object = choices[i];
                if ((object instanceof String)) {
                    PlainSelectableEditField p = new PlainSelectableEditField((String) object, 0,
                            this);
                    if (CustomObjectChoiceField.this.textFont != null)
                        p.setTextFont(CustomObjectChoiceField.this.textFont);
                    add(p);
                }
            }

            if ((selected > -1) && (selected < getFieldCount())) {
                getField(selected).setFocus();
            }

            setBackground(BackgroundFactory.createSolidTransparentBackground(16777215, 0));

            setBorder(BorderFactory.createSimpleBorder(new XYEdges(1, 1, 1, 1), 2));

            setBackground(BackgroundFactory.createSolidBackground(14671839));
        }

        public void paint(Graphics g) {
            g.clear();
            g.setColor(16761035);
            g.fillRoundRect(5, 5, 300, 30, 5, 5);

            g.setColor(16119285);
            int c = 5;
            for (int i = 0; i < CustomObjectChoiceField.this.choices.length; i++) {
                g.drawText(CustomObjectChoiceField.this.choices[i].toString(), 7, 5 + c);
                c += g.getFont().getAdvance(CustomObjectChoiceField.this.choices[i].toString());
            }
        }

        public void fieldChanged(Field field, int context) {
            if ((this.listener != null) && ((field instanceof PlainSelectableEditField))) {
                this.listener.selected(((PlainSelectableEditField) field).getLabel());
                close();
            }
        }

        public void close() {
            UiApplication.getUiApplication().popScreen(this);
        }

        public boolean keyChar(char key, int status, int time) {
            switch (key) {
            case '\n':
                break;
            case '\033':
                CustomObjectChoiceField.this.isShown = false;
                close();
                break;
            default:
                return super.keyChar(key, status, time);
            }
            return false;
        }

        public boolean keyDown(int keycode, int time) {
            return false;
        }

        public boolean keyRepeat(int keycode, int time) {
            return false;
        }

        public boolean keyStatus(int keycode, int time) {
            return false;
        }

        public boolean keyUp(int keycode, int time) {
            return false;
        }

        protected void sublayout(int width, int height) {
            super.sublayout(width, height);

            setPosition(5, 30);
        }
    }
}
